// x + 5;这个是语句  语句的返回值是一个空的tuple()
// x + 5这个是表达式  返回值就是x+5
fn plus_five(x: i32) -> i32 {
    x + 5
}

fn is_num(x: i32) {
    // if x % 2 == 0 {
    //     println!("2");
    // } else if x % 3 == 0 {
    //     println!("3");
    // } else if x % 7 == 0 {
    //     println!("7");
    // };

    match x {
        x if x % 2 == 0 => println!("2"),
        x if x % 3 == 0 => println!("3"),
        x if x % 7 == 0 => println!("7"),
        _ => println!("-"),
    }
}

fn main() {
    let _a = 2 + 20;
    let _b = 32 / 24;
    let _c = 32.0 / 24.3;
    let _d = 64 % 4;

    let x: i32 = plus_five(5);

    println!("fn:{}", x);

    is_num(5);

    // let number = if true { 5 } else { "00" };   返回值的类型必须相同
    let mut r = 0;

    let result = loop {
        r += 1;
        if r == 10 {
            break r * 2;
        }
    };

    println!("result:{}", result);

    let arr = [10, 20, 30, 40];
    for a_i in arr.iter() {
        println!("arr item:{}", a_i);
    }

    // -----堆栈
    let mut s = String::from("hello"); // ::表示from是String类型下的函数  - 这类字符串是可以被修改的

    s.push_str(", wORLD");
    println!("{}", s);

    // 函数和所有权
    let s_1 = String::from("hello world");

    log_str(s_1); // 这里的s_1的所有权已经到log_str方法里了

    // println!("1,{}",s_1); // 这里的s_1 已经离开了作用域  drop直接释放了他的内存

    let s_2 = 32;

    log_number(s_2);

    println!("1,{}", s_2);

    let s_3 = String::from("hello");

    let s_4: String = back_str(s_3); //这里的s_3的所有权已经通过back_str函数交给了s_4  drop不清除它
    println!("s_3 :  {}", s_4);

    // 引用&  和所有权   引用不影响所有权
    // 引用作为参数的行为叫做借用  不可以修改借用的东西
    let s_5 = String::from("hello");
    println!("s_5:  {}", brrow_str(&s_5));

    // 可变引用
    let mut s_6 = String::from("hello");

    println!("s_6_len:{} , s_6:{}", brrow_edit_str(&mut s_6), s_6);

    // 悬空引用，即引用的地址内存被释放了，rust不会出现这个情况

    // ------切片 
    // 不持有所有权的数据类型

    //   &变量[开始..结束] [开始..结束)   开始如果是0可省略  结束如果是结尾也可以省略

    //字符串切片
    println!("slice :: {}" ,first_str("hello,world"))
}

fn log_str(s: String) {
    println!("{}", s)
}

fn log_number(n: i32) {
    println!("{}", n)
}

fn back_str(str: String) -> String {
    str
}

// 借用
fn brrow_str(str: &String) -> usize {
    str.len()
}

fn brrow_edit_str(str: &mut String) -> usize {
    str.push_str(" world");
    str.len()
}

fn first_str(str: &str) -> &str {
    let bytes = str.as_bytes();
    for (i,&item) in bytes.iter().enumerate(){
        if item == b' ' {
            return &str[..i];
        }
    }
    &str[..]
}
